package com.ywu.application.standard.container.util;

import com.jcraft.jsch.*;
import com.ywu.boot.exception.YwuRuntimeException;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.util.Objects;

/**
 * @ClassName SSHUtils
 * @Description TODO
 * @Author GroundDemo
 * @Date 2024/3/5 21:13
 * @Version 1.0
 **/
@Slf4j
public class SSHUtils {

    /**
    * @Author GroundDemo
    * @Description 执行ssh指令
    * @Date 21:16 2024/3/5
    * @Param [sshHost, sshPort, sshUsername, sshPassword, command]
    * @return void
    **/
    public static String execCommand(String sshHost, Integer sshPort, String sshUsername, String sshPassword, String command) throws Exception{
        log.debug("execCommand command is {}", command);
        Session session = null;
        ChannelExec channel = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(sshUsername, sshHost, sshPort);
            session.setPassword(sshPassword);
            session.setConfig("StrictHostKeyChecking", "no"); // 关闭主机密钥校验
            session.connect();
            channel = (ChannelExec) session.openChannel("exec");
            channel.setCommand(command); // 要执行的Linux命令
            channel.setInputStream(null);
            ByteArrayOutputStream errOutputStream = new ByteArrayOutputStream();
            channel.setErrStream(errOutputStream);
            ByteArrayOutputStream extOutputStream = new ByteArrayOutputStream();
            channel.setExtOutputStream(extOutputStream);
            channel.setInputStream(null);
            channel.connect();
            InputStream inputStream = channel.getInputStream();
            while (!channel.isClosed()) {
                Thread.sleep(500);
            }
            String extRes = extOutputStream.toString();
            String errRes = errOutputStream.toString();
            byte[] buffer = new byte[1024];
            StringBuilder outputBuilder = new StringBuilder();
            while (true) {
                int bytesRead = inputStream.read(buffer);
                if (bytesRead <= 0) {
                    break;
                }
                outputBuilder.append(new String(buffer, 0, bytesRead));
            }
            outputBuilder.append(extRes).append(errRes);
            log.debug("execCommand out is {}", outputBuilder);
            return outputBuilder.toString();
        } finally {
            if (Objects.nonNull(channel)) {
                channel.disconnect();
            }
            if (Objects.nonNull(session)) {
                session.disconnect();
            }
        }
    }

    /**
    * @Author GroundDemo
    * @Description 下载文件
    * @Date 18:17 2024/7/13
    * @Param [sshHost, sshPort, sshUsername, sshPassword, filePath, fileName, localFilePath, localFileName]
    * @return boolean
    **/
    public static boolean downloadFile(String sshHost, Integer sshPort, String sshUsername, String sshPassword,
                                    String filePath, String fileName, String localFilePath, String localFileName) throws Exception{
        Channel channel = null;
        InputStream inputStream = null;
        FileOutputStream fileOutputStream = null;
        boolean flag = true;
        Session session = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(sshUsername, sshHost, sshPort);
            session.setPassword(sshPassword);
            session.setConfig("StrictHostKeyChecking", "no"); // 关闭主机密钥校验
            session.connect();
            //创建sftp通信通道
            channel = session.openChannel("sftp");
            channel.connect();
            ChannelSftp sftp = (ChannelSftp) channel;
            //进入服务器指定的文件夹
            sftp.cd(filePath);
            inputStream = sftp.get(fileName);
            BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
            // 判断文件夹是否存在
            File file = new File(localFilePath);
            if (!file.exists()) {
                boolean mkdirs = file.mkdirs();
                if (!mkdirs) {
                    throw new YwuRuntimeException("file create error " + localFilePath);
                }
            }
            fileOutputStream = new FileOutputStream(localFilePath + "/" + localFileName);
            BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            byte[] buf = new byte[1024];
            int length = bufferedInputStream.read(buf);
            while (-1 != length) {
                bufferedOutputStream.write(buf, 0, length);
                length = bufferedInputStream.read(buf);
            }
            bufferedInputStream.close();
            bufferedOutputStream.close();
        } catch (JSchException | SftpException | IOException e) {
            flag = false;
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
        }
        return flag;
    }

    /**
    * @Author GroundDemo
    * @Description 上传文件
    * @Date 18:17 2024/7/13
    * @Param [sshHost, sshPort, sshUserName, sshPassword, frpcFilePath, frpcFileName, localFilePath, localFileName]
    * @return void
    **/
    public static void uploadFile(String sshHost, Integer sshPort, String sshUserName, String sshPassword,
                                  String frpcFilePath, String frpcFileName, String localFilePath, String localFileName) throws IOException {
        Channel channel = null;
        FileInputStream fileInputStream = null;
        BufferedInputStream bufferedInputStream = null;
        Session session = null;
        OutputStream put = null;
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(sshUserName, sshHost, sshPort);
            session.setPassword(sshPassword);
            session.setConfig("StrictHostKeyChecking", "no"); // 关闭主机密钥校验
            session.connect();
            channel = session.openChannel("sftp");
            channel.connect();
            ChannelSftp sftp = (ChannelSftp) channel;
            sftp.cd(frpcFilePath);
            put = sftp.put(frpcFileName);
            // 读取文件
            File file = new File(localFilePath + "/" + localFileName);
            fileInputStream = new FileInputStream(file);
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            byte[] buf = new byte[1024];
            int length = bufferedInputStream.read(buf);
            while (-1 != length) {
                put.write(buf, 0, length);
                length = bufferedInputStream.read(buf);
            }
            put.flush();
        } catch (JSchException | SftpException | IOException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
            if (bufferedInputStream != null) {
                bufferedInputStream.close();
            }
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
        }
    }
}
